﻿Imports System.ComponentModel
Imports System.Collections.ObjectModel
Imports System.IO.Packaging
Imports Q2Q
Namespace Shows

	''' <summary>
	''' A ShowFile contains a cuelist and other operations to allow for operation and saving of the file.
	''' </summary>
	''' <remarks></remarks>
	<Serializable>
	<Xml.Serialization.XmlInclude(GetType(Cues.Audio))>
	<Xml.Serialization.XmlInclude(GetType(Cues.Transport))>
	<Xml.Serialization.XmlInclude(GetType(Cues.Stack))>
	<Xml.Serialization.XmlInclude(GetType(Collections.CueList))>
	<Xml.Serialization.XmlInclude(GetType(Audio.Devices.DeviceChannel))>
	Public Class ShowFile

#Region "Notification"
		Implements INotifyPropertyChanged
		<NonSerialized()> Public Event PropertyChanged(sender As Object, e As PropertyChangedEventArgs) Implements INotifyPropertyChanged.PropertyChanged

		Friend Overridable Sub RaisePropertyChanged(ByVal sProp As String)
			RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(sProp))
		End Sub
#End Region

		''' <summary>
		''' Fires when the "PropertyChanged" event is fired by a cue in the cue list. This way we can notify the user the project hasn't been saved. If the status property changes this is ignored.
		''' </summary>
		''' <param name="sender"></param>
		''' <param name="e"></param>
		''' <remarks></remarks>
		Public Sub ACueIsChanged(sender As Object, e As PropertyChangedEventArgs)
			If e.PropertyName <> "Status" AndAlso e.PropertyName <> "CurrentTime" Then
				IsSaved = False
			ElseIf e.PropertyName = "Status" Then
				If CType(sender, Cues.CueBase).ParentCue <> "" Then
					Try
						CType(CueList.FindCueByNumber(CType(sender, Cues.CueBase).ParentCue), Cues.Stack).UpdateStatus()
					Catch
					End Try
				End If
				RaisePropertyChanged("ActiveCueCount")
			End If
		End Sub

#Region "Properties"

		Private CueListStatic As String = "CueList"
		Private CueListProperty As New Collections.CueList
		''' <summary>
		''' A CueList class that holds a list of objects that inherit CueBase.
		''' </summary>
		''' <value></value>
		''' <returns></returns>
		''' <remarks></remarks>
		<Xml.Serialization.XmlIgnore> Public Property CueList As Collections.CueList
			Get
				Return CueListProperty
			End Get
			Set(value As Collections.CueList)
				If CueListProperty IsNot value Then
					value.Sort()
					CueListProperty = value
					RaisePropertyChanged(CueListStatic)
					IsSaved = False
				End If
			End Set
		End Property

		''' <summary>
		''' This is used ONLY for serialization to and from XML. Do not touch this member from within code or you could overwrite your actual cuelist.
		''' </summary>
		''' <value></value>
		''' <returns></returns>
		''' <remarks></remarks>
		<Xml.Serialization.XmlElement("Cue")> Public Property CueListSerializer As List(Of Cues.CueBase)
			Get
				Return CueList.ToList()
			End Get
			Set(value As List(Of Cues.CueBase))
				For i = 0 To value.Count - 1
					CueList.Add(value(i))
				Next
			End Set
		End Property

		''' <summary>
		''' Returns an observable collection of cues, based on the cue list sorted set.
		''' </summary>
		''' <value></value>
		''' <returns></returns>
		''' <remarks></remarks>
		<Xml.Serialization.XmlIgnore()> Public ReadOnly Property CueListCollection As List(Of Cues.CueBase)	'ObservableCollection(Of Cues.CueBase)
			Get
				'Return New ObservableCollection(Of Cues.CueBase)(CueListProperty)
				Return CueList.ToList()
			End Get
		End Property

		''' <summary>
		''' Returns a list of currently active cues in the show's primary cue list.
		''' </summary>
		''' <value></value>
		''' <returns></returns>
		''' <remarks></remarks>
		<Xml.Serialization.XmlIgnore()> Public ReadOnly Property ActiveCues As SortedSet(Of Cues.CueBase)
			Get
				Return New SortedSet(Of Cues.CueBase)(CueList.ToList.Where(Function(c) CType(c, Cues.CueBase).Status = Cues.CueStatus.Active OrElse CType(c, Cues.CueBase).Status = Cues.CueStatus.Cued))
			End Get
		End Property

		''' <summary>
		''' Returns the number of active cues in the show's primary cue list.
		''' </summary>
		''' <value></value>
		''' <returns></returns>
		''' <remarks></remarks>
		<Xml.Serialization.XmlIgnore()> Public ReadOnly Property ActiveCueCount As Integer
			Get
				Return CueList.Where(Function(c) CType(c, Cues.CueBase).Status = Cues.CueStatus.Active).Count
			End Get
		End Property

		''' <summary>
		''' Returns true if the user has saved the show as an archive.
		''' </summary>
		''' <value></value>
		''' <returns></returns>
		''' <remarks></remarks>
		Public Property IsArchive As Boolean = False


		Private IsSavedProperty As Boolean = False
		''' <summary>
		''' Indicates whether the project file has been saved since changes were made.
		''' </summary>
		''' <value></value>
		''' <returns></returns>
		''' <remarks></remarks>
		<Xml.Serialization.XmlIgnore()> Public Property IsSaved As Boolean
			Get
				Return IsSavedProperty
			End Get
			Set(value As Boolean)
				If IsSavedProperty <> value Then
					IsSavedProperty = value
					RaisePropertyChanged("IsSaved")
				End If
				RaisePropertyChanged("DisplayName")
			End Set
		End Property

		''' <summary>
		''' The project file's save path.
		''' </summary>
		''' <value></value>
		''' <returns></returns>
		''' <remarks></remarks>
		Public Property Path As String = ""

		''' <summary>
		''' The project file's file name.
		''' </summary>
		''' <value></value>
		''' <returns></returns>
		''' <remarks></remarks>
		Public Property Name As String = "Untitled Project"

		''' <summary>
		''' Returns the name with an astrix appended if the showfile hasn't been saved.
		''' </summary>
		''' <value></value>
		''' <returns></returns>
		''' <remarks></remarks>
		<Xml.Serialization.XmlIgnore()> Public ReadOnly Property DisplayName As String
			Get
				Dim ns As String = Name
				If IsSaved = False Then
					ns += "*"
				End If
				If CueList.Count > 1 OrElse CueList.Count = 0 Then
					ns += "  •  " & CueList.Count & " Cues"
				Else
					ns += "  •  " & CueList.Count & " Cue"
				End If
				Return ns
			End Get
		End Property

		''' <summary>
		''' The settings for audio DeviceChannel 0/1
		''' </summary>
		''' <value></value>
		''' <returns></returns>
		''' <remarks></remarks>
		Public Property Channel01Settings As Audio.Devices.DeviceChannel
			Get
				If Channel01SettingsProperty Is Nothing Then
					Channel01SettingsProperty = New Audio.Devices.DeviceChannel()
					Channel01SettingsProperty.ChannelID = 0
					Channel01SettingsProperty.IsDefault = True
					Channel01SettingsProperty.IsEnabled = True
				End If
				Return Channel01SettingsProperty
			End Get
			Set(value As Audio.Devices.DeviceChannel)
				Channel01SettingsProperty = value
				RaisePropertyChanged("Channel01Settings")
				IsSaved = False
			End Set
		End Property
		Private Channel01SettingsProperty As Audio.Devices.DeviceChannel

		''' <summary>
		''' The settings for audio DeviceChannel 2/3
		''' </summary>
		''' <value></value>
		''' <returns></returns>
		''' <remarks></remarks>
		Public Property Channel23Settings As Audio.Devices.DeviceChannel
			Get
				If Channel23SettingsProperty Is Nothing Then
					Channel23SettingsProperty = New Audio.Devices.DeviceChannel()
					Channel23SettingsProperty.ChannelID = 1
					Channel23SettingsProperty.IsDefault = False
					Channel23SettingsProperty.IsEnabled = False
				End If
				Return Channel23SettingsProperty
			End Get
			Set(value As Audio.Devices.DeviceChannel)
				Channel23SettingsProperty = value
				RaisePropertyChanged("Channel23Settings")
				IsSaved = False
			End Set
		End Property
		Private Channel23SettingsProperty As Audio.Devices.DeviceChannel

		''' <summary>
		''' The settings for audio DeviceChannel 4/5
		''' </summary>
		''' <value></value>
		''' <returns></returns>
		''' <remarks></remarks>
		Public Property Channel45Settings As Audio.Devices.DeviceChannel
			Get
				If Channel45SettingsProperty Is Nothing Then
					Channel45SettingsProperty = New Audio.Devices.DeviceChannel()
					Channel45SettingsProperty.ChannelID = 2
					Channel45SettingsProperty.IsDefault = False
					Channel45SettingsProperty.IsEnabled = False
				End If
				Return Channel45SettingsProperty
			End Get
			Set(value As Audio.Devices.DeviceChannel)
				Channel45SettingsProperty = value
				RaisePropertyChanged("Channel45Settings")
				IsSaved = False
			End Set
		End Property
		Private Channel45SettingsProperty As Audio.Devices.DeviceChannel

		''' <summary>
		''' The settings for audio DeviceChannel 6/7
		''' </summary>
		''' <value></value>
		''' <returns></returns>
		''' <remarks></remarks>
		Public Property Channel67Settings As Audio.Devices.DeviceChannel
			Get
				If Channel67SettingsProperty Is Nothing Then
					Channel67SettingsProperty = New Audio.Devices.DeviceChannel()
					Channel67SettingsProperty.ChannelID = 3
					Channel67SettingsProperty.IsDefault = False
					Channel67SettingsProperty.IsEnabled = False
				End If
				Return Channel67SettingsProperty
			End Get
			Set(value As Audio.Devices.DeviceChannel)
				Channel67SettingsProperty = value
				RaisePropertyChanged("Channel67Settings")
				IsSaved = False
			End Set
		End Property
		Private Channel67SettingsProperty As Audio.Devices.DeviceChannel

#End Region

#Region "Save and Load"

		''' <summary>
		''' Returns a project file loaded from a file. If invalid format occurrs, throws an exception.
		''' </summary>
		''' <param name="file"></param>
		''' <returns></returns>
		''' <remarks></remarks>
		Public Shared Async Function Load(ByVal file As String) As Task(Of ShowFile)
			If My.Application.Show.ShowFile.IsSaved = False AndAlso My.Application.Show.ShowFile.CueList.Count > 0 Then
				If MsgBox("The current show has not been saved. Are you sure you want to continue?", MsgBoxStyle.YesNo) = MsgBoxResult.No Then
					My.Application.Show.Console.SendMessage("Canceled loading a project file.")
					Return Nothing
				End If
			End If

			'Await My.Application.Show.StopAllCues()
			Await My.Application.Show.ShowFile.CueList.StopAllCues()

			Try
				Dim serial As New IO.FileStream(file, IO.FileMode.Open)
				Dim binaryFormatter As New Runtime.Serialization.Formatters.Binary.BinaryFormatter()
				Dim project As ShowFile = binaryFormatter.Deserialize(serial)
				serial.Close()

				'Check to see if the file thinks it belongs where it is located.
				'If not, update the path info and resave the file.
				Dim fi As New IO.FileInfo(file)
				Dim UpdateSave As Boolean = False
				If project.Path <> fi.DirectoryName Then
					project.Path = fi.DirectoryName
					UpdateSave = True
				End If
				If project.Name <> fi.Name Then
					project.Name = fi.Name
					UpdateSave = True
				End If
				If UpdateSave Then
					project.Save()
				End If


				If My.Settings.RecentProjects Is Nothing Then My.Settings.RecentProjects = New RecentShowsList
				My.Settings.RecentProjects.AddProject(file)
				My.Settings.Save()

				For Each cue As Cues.CueBase In project.CueList
					PrepCue(cue, project, file)
				Next


				project.CueList.Min.Status = Cues.CueStatus.Cued

				If project.Path <> FileIO.FileSystem.GetParentPath(file) Then
					project.Path = FileIO.FileSystem.GetParentPath(file)
				End If

				Return project
			Catch ex As Exception
				My.Application.Show.Console.SendMessage("There was a problem loading a show file.", ex)
				MsgBox("There was an error opening this file. Please try again. If the problem persists you may have a corrupt project file.")
				Return Nothing
			End Try
		End Function

		''' <summary>
		''' Creates an open file dialog to select a project file from. Returns the selected project as a ShowFile.
		''' </summary>
		''' <returns></returns>
		''' <remarks></remarks>
		Public Shared Async Function Load() As Task(Of ShowFile) ' Task(Of ShowFile)
			If My.Application.Show.ShowFile.IsSaved = False AndAlso My.Application.Show.ShowFile.CueList.Count > 0 Then
				If MsgBox("The current show has not been saved. Are you sure you want to continue?", MsgBoxStyle.YesNo) = MsgBoxResult.No Then
					My.Application.Show.Console.SendMessage("The user canceled the loading of a project file.")
					Return Nothing
				End If
			End If
			Dim b As New Microsoft.Win32.OpenFileDialog()
			b.Multiselect = False
			b.Title = "Select a Mixr Project to Open"
			b.DefaultExt = ".mxr"
			b.Filter = "Cue2Q Projects (.q2q)|*.q2q"
			b.ShowDialog()
			If b.FileName = "" Then
				Return Nothing
			End If
			If b.FileName.EndsWith(".q2q") = False Then
				My.Application.Show.Console.SendMessage("An invalid show file was selected. Please select a q2q file to open.")
				MsgBox("Please select a valid project file to open.", MsgBoxStyle.Critical)
				Return Nothing
			End If
			Return Await Load(b.FileName)
		End Function

		''' <summary>
		''' Saves a project file if it has a path and name, otherwise calls save-as to get a director and name to save to.
		''' </summary>
		''' <remarks></remarks>
		Public Sub Save(Optional ForceSave As Boolean = False)
			If My.Application.Show.ShowFile.IsSaved Then
				If Not ForceSave Then Return
			End If
			If Path = "" OrElse IO.Directory.Exists(Path) = False OrElse Name = "" Then
				SaveAs()
				Return
			End If
			IsSaved = True
			Dim serial As IO.FileStream = Nothing


			Try
				If Not My.Settings.SaveAsXml Then
					serial = New IO.FileStream(Path & "\" & Name & ".temp", IO.FileMode.Create)
					Dim binaryFormatter As New Runtime.Serialization.Formatters.Binary.BinaryFormatter()
					binaryFormatter.Serialize(serial, Me)
					Dim fi As New IO.FileInfo(Path & "\" & Name & ".temp")
				Else
					Dim x As New Xml.Serialization.XmlSerializer(Me.GetType)
					x.Serialize(New IO.StreamWriter(Path & "\" & Name & "x.temp"), Me)
				End If
			Catch ex As Exception
				IsSaved = False
				My.Application.Show.Console.SendMessage("An error occurred when saving the show file.", ex)
				Return
			Finally
				serial.Close()
			End Try

			Try
				If Not My.Settings.SaveAsXml Then
					IO.File.Delete(Path & "\" & Name)
					FileIO.FileSystem.RenameFile(Path & "\" & Name & ".temp", Name)
				Else
					IO.File.Delete(Path & "\" & Name & "x")
					FileIO.FileSystem.RenameFile(Path & "\" & Name & "x.temp", Name & "x")
				End If
			Catch ex As Exception
				MsgBox("There was a problem saving the show file! Please make sure your project saves properly before closing the application!")
				My.Application.Show.Console.SendMessage("An error occurred when saving the show file. Please make sure your project has saved properly!", ex)
				IsSaved = False
				Return
			End Try

			If IsSaved = False Then
				Return
			End If

			If My.Settings.RecentProjects Is Nothing Then My.Settings.RecentProjects = New RecentShowsList
			My.Settings.RecentProjects.AddProject(Me.Path & "\" & Me.Name)
			My.Settings.Save()
			My.Application.Show.Console.SendMessage("The show file was saved.")


		End Sub

		''' <summary>
		''' Opens a dialog to locate the path and name you want to save to. Then calls Save().
		''' </summary>
		''' <remarks></remarks>
		Public Sub SaveAs()

			Dim browser As New Microsoft.Win32.SaveFileDialog()
			browser.DefaultExt = ".q2q"
			browser.Filter = "Cue2Q Projects (.q2q)|*.q2q"

			If Path = "" Then
				browser.InitialDirectory = My.Computer.FileSystem.SpecialDirectories.MyDocuments
			Else
				browser.InitialDirectory = Path
			End If

			browser.Title = "Save Your Project File"

			If browser.ShowDialog() = True Then
				Name = browser.SafeFileName
				Path = New IO.FileInfo(browser.FileName).DirectoryName
			Else
				My.Application.Show.Console.SendMessage("The user canceled out of saving the show file.")
				Return
			End If

			Save(True)

		End Sub


		Public Sub Consolidate()
			If Not Path.EndsWith(".qArchive") Then
				Path = Path & "\" & Name.Replace(".q2q", "") & ".qArchive"
				If Not FileIO.FileSystem.DirectoryExists(Path) Then
					FileIO.FileSystem.CreateDirectory(Path)
					FileIO.FileSystem.CreateDirectory(Path & "\AudioFiles")
				End If
			End If

			For Each ac As Cues.Audio In CueList.OfType(Of Cues.Audio)()
				If ac.FileName Is Nothing OrElse ac.FileName = "" Then
					Continue For
				End If
				Dim OriginalPath As New String("")
				If FileIO.FileSystem.GetParentPath(ac.FileName) <> Path & "\AudioFiles" Then
					OriginalPath = New String(ac.FileName.ToCharArray)
					ac.FileName = Path & "\AudioFiles\" & ac.ShortFileName
				End If
				If Not FileIO.FileSystem.FileExists(ac.FileName) AndAlso OriginalPath <> "" Then
					'FileIO.FileSystem.CopyFile(OriginalPath, Path & "\AudioFiles")
					'FileIO.FileSystem.CopyFile(OriginalPath, Path & "\AudioFiles", True)
					Dim fi As IO.FileInfo = FileIO.FileSystem.GetFileInfo(OriginalPath)
					fi.CopyTo(Path & "\AudioFiles\" & fi.Name)
				End If
			Next
			IsArchive = True
			Save()
		End Sub

		Public Shared Sub Consolidate(ByRef ShowFile As ShowFile)
			Dim IsNewSave As Boolean = False

			If ShowFile.Name = "" Then
				ShowFile.Save()
				IsNewSave = True
			End If

			Dim OriginalPath As String = ShowFile.Path.Replace("a", "a") & "\" & ShowFile.Name

			Dim NewPath As String = ShowFile.Path.Replace("a", "a")



			If Not ShowFile.Path.EndsWith(".qArchive") Then
				NewPath = ShowFile.Path.Replace("a", "a") & "\" & ShowFile.Name.Replace(".q2q", "") & ".qArchive"
				IO.Directory.CreateDirectory(NewPath)
				If Not IO.Directory.Exists(NewPath) Then
					My.Application.Show.Console.SendMessage("There was a problem creating the show folder.")
					Return
				End If
				IO.Directory.CreateDirectory(NewPath & "\AudioFiles")
				If Not IO.Directory.Exists(NewPath & "\AudioFiles") Then
					My.Application.Show.Console.SendMessage("There was a problem creating the audio file folder.")
					Return
				End If


				Try
					With My.Settings.RecentProjects
						If .Project2 <> "" Then
							.Project2 = .Project3
							.Project3 = .Project4
							.Project4 = ""
						End If
					End With
				Catch
				Finally
					My.Settings.Save()
				End Try
			End If

			Try
				For Each c As Cues.Audio In ShowFile.CueList.OfType(Of Cues.Audio)()
					If Not IO.File.Exists(NewPath & "\AudioFiles\" & c.ShortFileName) Then
						IO.File.Copy(c.FileName, NewPath & "\AudioFiles\" & c.ShortFileName)
						c.FileName = c.ShortFileName
					End If
				Next
			Catch ex As Exception
				My.Application.Show.Console.SendMessage("There was a problem copying the files.", ex)
				IO.Directory.Delete(ShowFile.Path, FileIO.DeleteDirectoryOption.DeleteAllContents)
			End Try

			ShowFile.Path = NewPath.Replace("a", "a")
			ShowFile.IsArchive = True

			Try
				ShowFile.IsSaved = True
				Dim serial As IO.FileStream = Nothing
				'Try
				'	serial = New IO.FileStream(ShowFile.Path & "\" & ShowFile.Name & ".temp", IO.FileMode.Create)
				'	Dim binaryFormatter As New Runtime.Serialization.Formatters.Binary.BinaryFormatter()
				'	binaryFormatter.Serialize(serial, ShowFile)
				'Catch ex As Exception
				'	ShowFile.IsSaved = False
				'	My.Application.Show.Console.SendMessage("An error occurred when saving the show file.", ex)
				'Finally
				'	Try
				'		serial.Close()
				'		IO.File.Delete(ShowFile.Path & "\" & ShowFile.Name & ".temp")
				'	Catch ex As Exception
				'	End Try
				'End Try

				Try
					If Not My.Settings.SaveAsXml Then
						serial = New IO.FileStream(ShowFile.Path & "\" & ShowFile.Name & ".temp", IO.FileMode.Create)
						Dim binaryFormatter As New Runtime.Serialization.Formatters.Binary.BinaryFormatter()
						binaryFormatter.Serialize(serial, ShowFile)
					Else
						Dim x As New Xml.Serialization.XmlSerializer(ShowFile.GetType)
						x.Serialize(New IO.StreamWriter(ShowFile.Path & "\" & ShowFile.Name & "x.temp"), ShowFile)
					End If
				Catch ex As Exception
					ShowFile.IsSaved = False
					My.Application.Show.Console.SendMessage("An error occurred when saving the show file.", ex)
					Return
				Finally
					serial.Close()
				End Try
				Try
					If Not My.Settings.SaveAsXml Then
						IO.File.Delete(ShowFile.Path & "\" & ShowFile.Name)
						FileIO.FileSystem.RenameFile(ShowFile.Path & "\" & ShowFile.Name & ".temp", ShowFile.Name)
					Else
						IO.File.Delete(ShowFile.Path & "\" & ShowFile.Name & "x")
						FileIO.FileSystem.RenameFile(ShowFile.Path & "\" & ShowFile.Name & "x.temp", ShowFile.Name & "x")
					End If
				Catch ex As Exception
					MsgBox("There was a problem saving the show file! Please make sure your project saves properly before closing the application!")
					My.Application.Show.Console.SendMessage("An error occurred when saving the show file. Please make sure your project has saved properly!", ex)
					ShowFile.IsSaved = False
					Return
				End Try

				If ShowFile.IsSaved = False Then
					Return
				End If
				Try
					serial = New IO.FileStream(ShowFile.Path & "\" & ShowFile.Name, IO.FileMode.Create)
					Dim binaryFormatter As New Runtime.Serialization.Formatters.Binary.BinaryFormatter()
					binaryFormatter.Serialize(serial, ShowFile)
					serial.Close()
				Catch ex As Exception
					ShowFile.IsSaved = False
					My.Application.Show.Console.SendMessage("An error occurred when saving the show file.", ex)
					Return
				End Try

				If My.Settings.RecentProjects Is Nothing Then My.Settings.RecentProjects = New RecentShowsList
				My.Settings.RecentProjects.AddProject(ShowFile.Path & "\" & ShowFile.Name)
				My.Settings.Save()
				My.Application.Show.Console.SendMessage("The show file was saved.")

			Catch ex As Exception
				My.Application.Show.Console.SendMessage("There was a problem saving the project.", ex)
				IO.Directory.Delete(ShowFile.Path, FileIO.DeleteDirectoryOption.DeleteAllContents)
			Finally


			End Try

			If Not IsNewSave Then
				If MsgBox("You have created an archive of the project, which stores the project file inside. Do you wish to remove the old project file?", MsgBoxStyle.YesNo) = MsgBoxResult.Yes Then
					Try
						IO.File.Delete(OriginalPath)
						My.Application.Show.Console.SendMessage("The original project file was removed.")
					Catch ex As Exception
						My.Application.Show.Console.SendMessage("There was a problem remove the old project file.", ex)
					End Try
				End If
			End If
		End Sub

#End Region

#Region "Functionality"

		''' <summary>
		''' Assigns event handlers and ensures proper file pathing.
		''' </summary>
		''' <param name="cue"></param>
		''' <remarks></remarks>
		Private Shared Sub PrepCue(cue As Cues.CueBase, project As ShowFile, file As String)
			AddHandler cue.PropertyChanged, AddressOf project.ACueIsChanged
			cue.Status = Cues.CueStatus.Standby
			If cue.GetType Is GetType(Cues.Audio) AndAlso CType(cue, Cues.Audio).FileName <> "" AndAlso project.IsArchive Then
				If FileIO.FileSystem.FileExists(FileIO.FileSystem.GetParentPath(file) & "\AudioFiles\" & CType(cue, Cues.Audio).ShortFileName) Then
					CType(cue, Cues.Audio).FileName = FileIO.FileSystem.GetParentPath(file) & "\AudioFiles\" & CType(cue, Cues.Audio).ShortFileName
					CType(cue, Cues.Audio).CurrentTime = CType(cue, Cues.Audio).TotalTime.ToString("hh\:mm\:ss")
				Else
					CType(cue, Cues.Audio).CurrentTime = "File Not Found!"
				End If
			ElseIf cue.GetType Is GetType(Cues.Audio) AndAlso CType(cue, Cues.Audio).FileName <> "" Then
				If FileIO.FileSystem.FileExists(CType(cue, Cues.Audio).FileName) Then
					CType(cue, Cues.Audio).CurrentTime = CType(cue, Cues.Audio).TotalTime.ToString("hh\:mm\:ss")
				Else
					CType(cue, Cues.Audio).CurrentTime = "File Not Found!"
				End If
			End If
			If cue.GetType Is GetType(Cues.Stack) Then
				For Each c As Cues.CueBase In CType(cue, Cues.Stack).CueList
					PrepCue(c, project, file)
				Next
			End If
		End Sub

		''' <summary>
		''' Add a cue to the cue list.
		''' </summary>
		''' <param name="cue">The cue to add.</param>
		''' <remarks></remarks>
		Public Sub AddCue(cue As Cues.CueBase, Optional AlertOfChange As Boolean = True)
			If cue.Number = 0 Then
				If CueList.Count > 0 Then
					cue.Number = CType((CueList.Max.Number + 1).ToString.Split(".")(0), Double)
				Else
					cue.Number = 1
				End If
				CueList.Add(cue)
				AddHandler cue.PropertyChanged, AddressOf ACueIsChanged
				IsSaved = False
				If AlertOfChange Then
					RaisePropertyChanged(CueListStatic)
					RaisePropertyChanged("CueListCollection")
					My.Application.Show.Console.SendMessage("A cue was added to the project.")
				End If
			Else
				If CueList.Contains(cue) Then
					If MsgBox("A cue with this number already exists. Do you want to increment this number by .1 and retry?", MsgBoxStyle.YesNo) = MsgBoxResult.Yes Then
						cue.Number = CType((cue.Number + 1).ToString.Split(".")(0), Double)
						AddCue(cue, AlertOfChange)
						Return
					Else
						Return
					End If
				Else
					CueList.Add(cue)
					AddHandler cue.PropertyChanged, AddressOf ACueIsChanged
					IsSaved = False
					If AlertOfChange Then
						RaisePropertyChanged(CueListStatic)
						RaisePropertyChanged("CueListCollection")
						My.Application.Show.Console.SendMessage("A cue was added to the project.")
					End If
					Return
				End If
			End If
			CueList.Sort()
		End Sub

		Public Sub AddCues(cl As List(Of Cues.CueBase))
			For Each c As Cues.CueBase In cl
				AddCue(c, False)
			Next
			RaisePropertyChanged(CueListStatic)
			RaisePropertyChanged("CueListCollection")
			My.Application.Show.Console.SendMessage(String.Format("{0} cue(s) added to the project.", cl.Count))
		End Sub

		''' <summary>
		''' Remove a cue from the cue list.
		''' </summary>
		''' <param name="cue">The cue to remove from the list.</param>
		''' <remarks></remarks>
		Public Sub RemoveCue(cue As Cues.CueBase)
			If CueList.Remove(cue) Then
				RemoveHandler cue.PropertyChanged, AddressOf ACueIsChanged
				RaisePropertyChanged(CueListStatic)
				RaisePropertyChanged("CueListCollection")
				IsSaved = False
			End If
		End Sub

		''' <summary>
		''' Remove a cue from the cue list based on the cue's number.
		''' </summary>
		''' <param name="Number">The number of the cue to remove.</param>
		''' <remarks></remarks>
		Public Sub RemoveCue(Number As Double)
			For Each c As Cues.CueBase In CueList
				If c.Number = Number Then
					RemoveCue(c)
					RaisePropertyChanged(CueListStatic)
					RaisePropertyChanged("CueListCollection")
					IsSaved = False
					Return
				End If
			Next
		End Sub

		''' <summary>
		''' Returns true if the cue list contains a cue with the number provided, otherwise it returns false.
		''' </summary>
		''' <param name="Number">The cue number to check to see if exists.</param>
		''' <returns></returns>
		''' <remarks></remarks>
		Public Function Contains(Number As Double)
			For Each c As Cues.CueBase In CueList
				If c.Number = Number Then
					Return True
				End If
			Next
			Return False
		End Function

		''' <summary>
		''' Returns the last active cue in the cue list.
		''' </summary>
		''' <returns></returns>
		''' <remarks></remarks>
		Public Function LastActiveCue() As Cues.Audio
			Dim cl As New List(Of Cues.CueBase)
			For Each c As Cues.CueBase In CueList
				If c.Status = Cues.CueStatus.Active Then
					cl.Add(c)
				End If
			Next
			If cl.Count > 0 Then
				Return cl.Item(cl.Count - 1)
			Else
				Return Nothing
			End If
		End Function

#End Region

	End Class

End Namespace